package com.sharedlease.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sharedlease.dto.IndentDTO;
import com.sharedlease.entity.Product;
import com.sharedlease.mapper.ProductMapper;
import com.sharedlease.service.ProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sharedlease.utils.RedisUtils;
import org.omg.CORBA.OBJ_ADAPTER;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 吴钟富
 * @since 2021-03-02
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
    Jedis jedis = RedisUtils.getConnection();

    public Set<Long> recommandBaseUserCF(Long uid, List<IndentDTO> indentDTOS) {
        Map<Long, Set<Long>> map = new HashMap<>();
        for (IndentDTO indentDTO : indentDTOS) {
            Set<Long> set = new HashSet<>();
            if (map.get(indentDTO.uid) == null) {
                set.add(indentDTO.pid);
                map.put(indentDTO.uid, set);
            } else {
                set = map.get(indentDTO.uid);
                set.add(indentDTO.pid);
                map.put(indentDTO.uid, set);
            }
        }
        System.out.println("map:" + map);
        Map<Long, Double> pidAndSim = new HashMap<>();
        if (map.get(uid) == null) {
            Set<Long> noOrderRecmmand = new HashSet<>();
            for (Map.Entry<Long, Set<Long>> entry : map.entrySet()) {
                noOrderRecmmand.addAll(entry.getValue());
            }
            System.out.println("用户没有任何订单记录，订单表里的所有产品：" + noOrderRecmmand + ",总个数：" + noOrderRecmmand.size());
            return noOrderRecmmand;
        }
        Set<Long> temSet = new HashSet<>();
        for (Map.Entry<Long, Set<Long>> entry : map.entrySet()) {
            if (entry.getKey() != null && entry.getValue() != null && !entry.getKey().equals(uid)) {
                temSet.addAll(map.get(uid));
                temSet.retainAll(entry.getValue());
                pidAndSim.put(entry.getKey(), (double) temSet.size() / (entry.getValue().size() + map.get(uid).size() - temSet.size()));
            }
        }
        List<Map.Entry<Long, Double>> entryList1 = new ArrayList<>(pidAndSim.entrySet());
        System.out.println("所有用户和uid的相似度：" + entryList1);
        Collections.sort(entryList1, new Comparator<Map.Entry<Long, Double>>() {
            @Override
            public int compare(Map.Entry<Long, Double> me1, Map.Entry<Long, Double> me2) {
//                return me1.getKey().compareTo(me2.getKey()); // 升序排序
                //return me2.getKey().compareTo(me1.getKey()); // 降序排序
                return me2.getValue().compareTo(me1.getValue()); // 降序排序
            }
        });
        entryList1 = entryList1.stream().limit(3).collect(Collectors.toList());
        System.out.println("和uid相似度前三的：" + entryList1);
        Set<Long> pidsSet = new HashSet<>();
        for (Map.Entry<Long, Double> one : entryList1) {
            pidsSet.addAll(map.get(one.getKey()));
        }
        System.out.println("pidsSet:" + pidsSet);
        pidsSet.removeAll(map.get(uid));
        System.out.println("remmandPros:" + pidsSet);
        return pidsSet;

    }

    public Set<Long> recommandBaseItemCF(Long uid, List<IndentDTO> indentDTOS) {
        Map<Long, Set<Long>> map = new HashMap<>();
        Map<Long, Set<Long>> usermap = new HashMap<>();
        Set<Long> recommandpids = new HashSet<>();
        for (IndentDTO indentDTO : indentDTOS) {
            Set<Long> set = new HashSet<>();
            if (map.get(indentDTO.pid) == null) {
                set.add(indentDTO.uid);
                map.put(indentDTO.pid, set);
            } else {
                set = map.get(indentDTO.pid);
                set.add(indentDTO.uid);
                map.put(indentDTO.pid, set);
            }

            if (indentDTO.uid.equals(uid) && usermap.get(indentDTO.uid) == null) {
                Set<Long> set1 = new HashSet<>();
                set1.add(indentDTO.pid);
                usermap.put(indentDTO.uid, set1);
            } else if (indentDTO.uid.equals(uid) && usermap.get(indentDTO.uid) != null) {
                Set<Long> set1 = new HashSet<>();
                set1 = usermap.get(indentDTO.uid);
                set1.add(indentDTO.pid);
                usermap.put(indentDTO.uid, set1);
            }
        }
        System.out.println("usermap:" + usermap);
        System.out.println("map:" + map);
        if (usermap.get(uid) == null) {
            Set<Long> noOrderRecmmand = new HashSet<>();
            for (Map.Entry<Long, Set<Long>> entry : map.entrySet()) {
                noOrderRecmmand.add(entry.getKey());
            }
            System.out.println("用户没有任何订单记录，订单表里的所有产品：" + noOrderRecmmand + ",总个数：" + noOrderRecmmand.size());
            return noOrderRecmmand;
        }
        Set<Long> productSet = usermap.get(uid);
        for (Long pid : productSet) {
            Map<Long, Double> pidAndSim = new HashMap<>();
            HashSet<Long> temSet = new HashSet<>();
            for (Map.Entry<Long, Set<Long>> entry : map.entrySet()) {
                if (entry.getKey() != null && !entry.getKey().equals(pid)) {
                    temSet.addAll(map.get(pid));
                    temSet.retainAll(entry.getValue());
                    System.out.println(entry.getKey() + "与" + pid + "相似度：" + (double) temSet.size() / (entry.getValue().size() + map.get(pid).size() - temSet.size()) + "三个值分别是：" + temSet.size() + "," + entry.getValue().size() + "," + map.get(pid).size());
                    pidAndSim.put(entry.getKey(), (double) temSet.size() / (entry.getValue().size() + map.get(pid).size() - temSet.size()));
                }
            }
            List<Map.Entry<Long, Double>> entryList1 = new ArrayList<>(pidAndSim.entrySet());
            System.out.println("所有产品和" + pid + "的相似度：" + entryList1);
            Collections.sort(entryList1, new Comparator<Map.Entry<Long, Double>>() {
                @Override
                public int compare(Map.Entry<Long, Double> me1, Map.Entry<Long, Double> me2) {
//                return me1.getKey().compareTo(me2.getKey()); // 升序排序
                    //return me2.getKey().compareTo(me1.getKey()); // 降序排序
                    return me2.getValue().compareTo(me1.getValue()); // 降序排序
                }
            });

            entryList1 = entryList1.stream().limit(3).collect(Collectors.toList());
            System.out.println("和" + pid + "相似度前3的：" + entryList1);
            for (Map.Entry<Long, Double> one : entryList1) {
                recommandpids.add(one.getKey());
            }
        }
        System.out.println("协同产品：" + recommandpids);
        recommandpids.removeAll(usermap.get(uid));
        System.out.println("协同过滤产品:" + recommandpids);
        return recommandpids;

    }

    /**
     * 从redis中查询所有产品
     *
     * @return
     */
    public List<Product> getAllProductsFromRedis() {
        String allProducts = jedis.get("allProducts");
        if (allProducts==null||allProducts.length()==0){
            return null;
        }


//json转换为list
        List<Product> products = new ArrayList<Product>();
        products = JSONObject.parseArray(jedis.get("allProducts"),Product.class);
        return products;
//
    }

    /**
     * 讲所有产品的list保存到redis
     * @param list 所有产品
     */
    public void saveAllProductsToRedis(List<Product> list){
        //list转json
        String allProducts= JSON.toJSON(list).toString();
        //存储到redis
        jedis.set("allProducts",allProducts);
    }


}
